/*
 * MART.hpp
 *
 *  Created on: Jun 15, 2011
 *      Author: fqhuy
 */

#ifndef MART_HPP_
#define MART_HPP_

#include <cstdio>
#include "Common.hpp"
#include "DataStructures.hpp"
#include "HallCalibration.hpp"
#include "FunctionsListOld.hpp"
#include <cstring>
#include <cmath>
#include <stdint.h>

class MART {
private:
	long VoxelX, VoxelY, VoxelZ, nz, indexcheck;
	float Voxel_size, Voxel_volume;

	inline char* IntToStr(const int num) {
		char* re = new char[256];
		sprintf(re, "%d", num);
		return re;
	}

	inline char* FloatToStr(const float num){
		char* re = new char[256];
		sprintf(re, "%f", num);
		return re;
	}

	inline float Norm(const uint8_t& num){
		return 1.0/num;
	}

	inline uint8_t UNorm(const float& num){
		return (uint8_t)255*num;
	}
public:
	Volume volume;
	char Output[256], Cord3d_File[256], Cameras_File[6][256], Images_File[6][256], Hint_File[6][256];
	FILE *fp1, *fp2, *fp3, *fp4, *fdata3d, *fdata_cord, *findex, *fpIntensity;
	float Start_VoxelX, End_VoxelX, Start_VoxelY, End_VoxelY, Start_VoxelZ,
			End_VoxelZ, Pixelsize, VPScaleFactor, Sphr, Cylr, Dcsphacyl, Dum, Mu,
			Dumi; // starting and ending voxel in real value

	uint16_t Hint[3][2000][2]; //[Number of images][Number of particles][2D coordinates]
	long PixelX, PixelY, Index, Index3d, ***Los_Voxels_Ind;

	//**Los_Voxels_Ind is the coordinate of the voxels which is in LOS of pixels
	int Voxel_Los, Itr, NoofFullItr, Current_Camera, Num_Camera, Image_Width, Image_Height, NCP, Num_Particles[3];
	float ***Intensity, ***W;
	int **Image, ***Images, Log, Use_Hint;
	double xc3d[MAX_NUM_CALIB_MARKERS], yc3d[MAX_NUM_CALIB_MARKERS], zc3d[MAX_NUM_CALIB_MARKERS], **xcl, **ycl/*[MAX_NUM_CALIB_MARKERS][Num_Camera]*/, C[12];
	Hall_Calibration h1;

	MART() {
	}

	MART(float Pixelsize, float VPScaleFactor, float Start_VoxelX,
			float End_VoxelX, float Start_VoxelY, float End_VoxelY,
			float Start_VoxelZ, float End_VoxelZ, long PixelX, long PixelY,
			int Itr, double xc3d[MAX_NUM_CALIB_MARKERS], double yc3d[MAX_NUM_CALIB_MARKERS], double zc3d[MAX_NUM_CALIB_MARKERS],
			double **xcl, double **ycl, char ***images, int ncp, float mu, int log=0, int use_hint=0);

	~MART(){
		Deallocate3D(Images,Num_Camera,Image_Height);
		Deallocate3D(Intensity,VoxelZ,VoxelY);
		Deallocate3D(W,PixelX*PixelY,nz);
		Deallocate3D(Los_Voxels_Ind,PixelX * PixelY + 1, nz + 1);
		Deallocate2D(xcl,MAX_NUM_CALIB_MARKERS);
		Deallocate2D(ycl,MAX_NUM_CALIB_MARKERS);
	}
	void ChooseCamera();

	void CalculateLOS(float x, float y, float Z, float *XY);

	void InitialiseWeight();

	void MARTUpdate();

	void StepRun(int j);

	void FullRun();

	void MeanFilter();

	void Decodexyz(long index, int maxx, int maxy, int maxz, int* a); // 3D/2D indices to linear index

};

#endif /* MART_HPP_ */
